/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2013/05/21
* File: Camera.h
* Blog: http://www.cnblogs.com/zengqh/
**/

#pragma once

#include "enn_platform_headers.h"
#include "enn_math.h"

namespace enn
{
class Camera
{
public:
	enum
	{
		PT_ORTHOGRAPHIC,
		PT_PERSPECTIVE
	};

	enum
	{
		DT_VIEW_MATRIX,
		DT_PROJ_MATRIX,
		DT_FRUSTUM
	};

public:
	Camera();
	virtual ~Camera();

	void setNearPlane(float near_clip);
	void setFarPlane(float far_clip);

	void setFov(float fov);

	void setOrthoSize(float othro);

	void setOrthoSize(const vec2f& size);

	void setAspectRatio(float ratio);

	float getNearClip() const;

	float getFarClip() const;

	float getFov() const;

	float getOrthoSize() const;

	float getAspectRatio() const;

	const Frustum& getFrustum() const;

	const Matrix4& getProjMatrix() const;

	const Matrix4& getViewMatrix() const;

	Frustum getSplitFrustum(float near_clip, float far_clip);

	Frustum getViewspaceFrustum() const;

	Frustum getViewSpaceSplitFrustum(float near_clip, float far_clip) const;

	vec2f worldToScreenPoint(const vec3f& worldPos);

	vec3f screenToWorldPoint(const vec3f& screenPos);

	vec3f getForwardVector();

	vec3f getRightVector();

	vec3f getUpVector();

	float getDistance(const vec3f& worldPos) const;

	float getDistanceSquared(const vec3f& worldPos) const;

	void setTransform(const vec3f& eye, const vec3f& target, const vec3f& up);
	void setTransform(const Matrix4& matWorld);

	void setProjType(uint32 type);
	uint32 getProjType() const;

	bool isPerspective() const;
	bool isOrthographic() const;

	Ray GetScreenRay(float x, float y);

protected:
	void makePerspectiveProj() const;
	void makeOrthoProj() const;

protected:
	Matrix4				view_matrix_;
	Matrix4				world_matrix_;
	mutable Matrix4		proj_matrix_;
	mutable Frustum		frustum_;
	uint32				proj_type_;
	float				near_clip_;
	float				far_clip_;
	float				fov_;
	float				ortho_size_;
	float				aspect_ratio_;
	mutable Flags32		dirty_flags_;
};
}